from http.client import CannotSendRequest

from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException

from error import Error


class BitcoinClient:
    def __init__(self, host, port, username, password):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.client = None
        self.connect()

    def connect(self):
        self.client = AuthServiceProxy(f"http://{self.username}:{self.password}@{self.host}:{self.port}")
        self.get_balance()

    def get_balance(self):
        try:
            balance = self.client.getbalance()
        except ConnectionRefusedError as e:
            raise Error(
                e,
                code=10061,
                message="连接失败，请检查客户端是否已启动，且正确配置 RPC。",
            )
        except JSONRPCException as e:
            if e.code == -342:
                raise Error(
                    e,
                    code=-342,
                    message="RPC 连接失败，请检查用户名和密码是否正确。",
                )
            elif e.code == -28:
                raise Error(
                    e,
                    code=-342,
                    message="RPC 连接失败，Bitcoin Core 正在启动网络线程。",
                )
            else:
                raise Error(
                    e,
                    code=e.code,
                    message=f"未知错误，错误信息：{e.message}"
                )
        except Exception as e:
            raise Error(
                e,
                code=0,
                message=f"未知错误。{str(e)}",
            )

        return balance

    def transfer(self, password, to_address, amount):
        try:
            self.client.walletpassphrase(password, 60)
            transaction_id = self.client.sendtoaddress(to_address, amount, 'Transaction')
        except JSONRPCException as e:
            if e.code == -14:
                raise Error(
                    e,
                    code=-14,
                    message="密码错误."
                )
            elif e.code == -28:
                raise Error(
                    e,
                    code=-28,
                    message="RPC 连接失败，Bitcoin Core 正在启动网络线程。"
                )
            else:
                raise Error(
                    e,
                    code=e.code,
                    message=f"未知错误，错误信息：{e.message}."
                )
        except ConnectionAbortedError as e:
            raise Error(
                e,
                code=10053,
                message="主动断开RPC连接。请重启客户端或检查网络连接。",
            )
        except CannotSendRequest as e:
            raise Error(
                e,
                code=10053002,
                message="已断开RPC连接。请重启客户端或检查网络连接。",
            )
        except ConnectionRefusedError as e:
            raise Error(
                e,
                code=10061,
                message="已断开RPC连接。请重启客户端或检查网络连接。",
            )
        except Exception as e:
            raise Error(
                e,
                code=0,
                message=f"未知错误。{str(e)}.",
            )


        return transaction_id


if __name__ == "__main__":
    client = BitcoinClient(
        host="127.0.0.1",
        port="18332",
        username="username1",
        password="password",
    )

    b = client.get_balance()

    print(f"Your balance is: {b}")
